/*
 * auto_proxy.c
 *
 * Created: 12/3/2011 11:53:30 AM
 *  Author: cmason1
 */

#ifndef F_CPU
#define F_CPU 10000000UL  // 10 MHz
#endif

#include <avr/io.h>
// #include <avr/interrupt.h>
#include <util/delay.h>

// #define sei()
// #define cli()

// #define PWM0_ON TCCR0A |= 2 << COM0A0; //turns non-inverting PWM0 on
// #define PWM0_OFF TCCR0A &= 0b00111111;//turns non-inverting PWM0 off
#define PWM1A_ON TCCR1A |= 2 << COM1A0; //turns non-inverting PWM1A on
#define PWM1A_OFF TCCR1A &= 0b00111111;//turns non-inverting PWM1A off
// #define PWM1B_ON TCCR1A |= 2 << COM1B0; //turns non-inverting PWM1B on
// #define PWM1B_OFF TCCR1A &= 0b11001111;//turns non-inverting PWM1B off

#define CounterON TCCR2B |= 5<<CS20;
#define CounterOFF TCCR2B &= ~(7<<CS20);

const int ADC_OFFSET = 3;

volatile int tenthmS;

// BCD for displaying number to 7 segment LED
char num[]={0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,0x80,0x90};
int k,i,led1,led2,led3;
// k is the value for display
// led1 is displayed in LED1
//led2 is displayed in LED2
//led3 is displayed in LED3

//DO NOT USE EXCEPT TO EXIT LOOPS!//
int delayloop( uint16_t ms )
{
  while ( ms )
  {
    _delay_ms( 1 );
    ms--;
  }
  return 0;  //return int to exit loops
}
void delayms( uint16_t ms )
{
  while (ms)
  {
    _delay_ms(1);
    ms--;
  }
}


// ISR (TIMER2_OVF_vect)
// {
//   tenthmS++;
// }

void PWM_init()
{
//   TCCR0A = 0; // turns off timer 0-A
  TCCR1A = 0; // turns off timer 1-A
//   TCCR1B = 0; // turns off timer 1-B
  TCCR2A = 0; // turns off timer 2-A

   ICR1 = 249; /* TOP seen above for timer 1 */
      
//   TCCR0A |= (1 << WGM01) | (1 << WGM00); // sets timer0 to Fast PWM
//   TCCR0B |= (1<<WGM02)| (1<<CS00);
   TCCR1A |= (1 << WGM11); // this and next line sets timer1 to
   TCCR1B |= (1 << WGM13) | (1 << WGM12) | (1<<CS10); // Fast PWM with prescaler=1
   TCCR2A |= (1<<COM2A0); //74.4kHz or 13 ms period
   TCCR2B |= (5<<CS20); //prescaler=1
   TCNT2 = 0;
//   TIMSK2 |= (1<<OCIE2A);
//   DDRD |= _BV(6);   // enable PD6 as output pin
   DDRB |= _BV(1) | _BV(3);// | _BV(2); // enables PB1&PB2 as output pins
   
//    TCCR0A |= 2 << 6; // sets COM0A(0&1) to 0x10 = non-inverting turns channel on
   TCCR1A |= 2 << 6; // sets COM1A(0&1) to 0x10 = non-inverting turns channel on
//   TCCR1A |= 2 << 4; // sets COM1B(0&1) to 0x10 = non-inverting turns channel on
//    CounterON;
/*   OCR0A = 250/2;  //sets the frequency to 40kHz*/
   OCR1A = 250/2; //sets the frequency to 40kHz with 50% duty cycle
//    OCR1B = 250/2; //sets the frequency to 40kHz
   OCR2A = 131; //sets the frequency to 74.4Hz period 13ms
        //which is how long it takes to travel 15ft
}

void ADC_init()
{
  //selects reference voltage to be external aka AREF
  ADMUX = (1<<REFS0) | ((1+ADC_OFFSET)<<MUX0)/* | (1<<ADLAR)*/;
  
  //enables ADC to operate at 156kHz and is triggered automatically
  ADCSRA = (1<<ADEN) | (6<<ADPS0) | (1<<ADATE) | (1<<ADSC);
//   ADMUX &= 0xF0; //disables whatever ADC channel is activated
//   ADMUX |= 0b00000100;//(1+ADC_OFFSET)<<MUX0;
  
}

int ADC_getTime(int channel)
{
  int time=0;
   int dumby = 7;
  
  TCNT2 = 0;
  _delay_ms(1); //waits until after 6inches, also until echo subsides
  CounterON;
    
//  sei();
//   dumby = TCNT2;
//   
  while(ADC < 11 && TCNT2 < 255) //while the value of of the return signal is less than 5mV*6
  {
     if(ADC > 11)
    {
      time = TCNT2;
    }
  }
    if(ADC > 4 && time>0)
  {
    time = TCNT2;
  }
  
  CounterOFF;
//  cli();
  if(time > 50)
  {
    time = time/2;
  }
  
  return time;
}

void Calc_Display(double seconds)
{   
   k= (((seconds*10)/2)*1130)-.1; //distance*10
//      k=seconds;
  led3 = (k-k%100)/100;   
  led2 = (k%100-k%10)/10;
  led1 = k%10;
    DDRD =0xFF; // Port D is set as output
  DDRC =0x07; // pin 0th, 1st and 2nd are set as output
  for (i=1000;i>0;i=i-3)  //update LEDs for 1 second
   {
     PORTC =0x01; // Turn on the LED1
     PORTD = num[led1];// Display value led1 on LED1
     delayms(1);  //POV time (1 ms to display each digit)
     PORTC =0x02; // Turn on the LED2
     PORTD = num[led2];// Display value led2 on LED2
     delayms(1);  //POV time (1 ms to display each digit)
     PORTC =0x04; // Turn on the LED3
     PORTD = num[led3];// Display value led3 on LED3
     delayms(1);  //POV time (1 ms to display each digit)
   }
}
int main(void)
{
    PWM_init();
  ADC_init();
  
  while(1)
    {
    int channel = 0;
    int num52uS;
    double Vin;
    int ADC_valuel;
    int ADC_valueh;
    uint16_t ADC_value;
//     float ADC_valueh;
//     PWM0_ON; //turns non-inverting PWM0 on
//     _delay_us(200);
//     PWM0_OFF;
//     num52uS = ADC_getTime(channel);
//     if(num52uS!=0)
//     {
//       Calc_Display(num52uS*.00005248);
//     }
    channel++;
    PWM1A_ON;
    _delay_us(200);
    PWM1A_OFF;
    num52uS = ADC_getTime(channel);
    ADC_valueh = ADCH;
    ADC_valuel = ADCL;
    ADC_value = ADCH*256 + ADCL;
    Vin = (ADC*5)/1024;
    ADC_valueh = (ADC_value*5)/256;
    if(num52uS!=0)
    {
      Calc_Display(num52uS*.00005);
    }
    _delay_ms(10);
//     channel++;
//     PWM1B_ON;
//     _delay_us(200);
//     PWM1B_OFF;
//     num52uS = ADC_getTime(channel);
//     
//     if(num52uS!=0)
//     {
//       Calc_Display(num52uS*.00005248);
//     }
    }
}